﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MUPModel = ESF.MUP.BasePlatform.Domain.Model;
using ESF.MUP.BasePlatform.Domain.Repositories;
using ESF.MUP.BasePlatform.Infrastructure.Dal;
using ESF.MUP.BasePlatform.Infrastructure.Validation;
using ESF.MUP.BasePlatform.ApplicationServices.Interfaces;

namespace ESF.MUP.BasePlatform.Services
{
    public class EnvironmentManagementService: IEnvironmentManagementService
    {
        #region "private members"
        private IEnvironmentRepository _environmentRepository;
        
        #endregion

        #region "Constructor"

        /// <summary>
        /// Create a new instance of environment management service
        /// </summary>
        /// <param name="environmentRepository"></param>
        public EnvironmentManagementService(IEnvironmentRepository environmentRepository)
        {
            if (environmentRepository == null)
                throw new ArgumentNullException("environmentRepository");

            _environmentRepository = environmentRepository;
        }
        #endregion

        #region "CRUD Operations"
        /// <summary>
        /// Find an environment in the repository
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public MUPModel.EnvironmentApplicatif FindEnvironment(String name)
        {
            var environment = _environmentRepository.GetFiltered(a => String.Compare(a.Name, name, StringComparison.InvariantCultureIgnoreCase) == 0)
                              .SingleOrDefault();

            return environment;

        }

        /// <summary>
        /// Add a new Environment
        /// </summary>
        /// <param name="environment"></param>
        /// <returns></returns>
        public MUPModel.EnvironmentApplicatif AddNewEnvironment(MUPModel.EnvironmentApplicatif environment)
        {
            if (environment == null)
                throw new ArgumentNullException("environment");

            if (!environment.IsTransient())
                throw new Exception(); //TODO Add message for add new failure on existing environment

            var existingEnvironment = this.FindEnvironment(environment.Name);

            if (existingEnvironment != null)
            {
                //TODO Add message for existing environment
                throw new Exception(); //TODO Add message for add new failure on existing environment
            }

            this.ValidateEnvironment(environment);

            _environmentRepository.Add(environment);
            _environmentRepository.UnitOfWork.Commit();

            return environment;

        }

        public void UpdateEnvironment(MUPModel.EnvironmentApplicatif environment)
        {
            if (environment == null || environment.IsTransient())
                throw new ArgumentException("environment"); //TODO Add argument exception message

            //Retrieve existing environment
            var existingEnvironment = _environmentRepository.Get(environment.Id);

            if (existingEnvironment == null)
            {
                //todo add error for missing entity between original call and now
                throw new Exception("error update");
            }
            else
            {
                _environmentRepository.Merge(existingEnvironment, environment);
                this.ValidateEnvironment(existingEnvironment);
                _environmentRepository.UnitOfWork.Commit();
            }
        }

        public void RemoveEnvironment(Int32 id)
        {
            //Retrieve existing environment
            var existingEnvironment = _environmentRepository.Get(id);

            if (existingEnvironment == null)
            {
                //todo add log for warning on already deleted entity
                throw new Exception("error update");
            }
            else
            {
                _environmentRepository.Remove(existingEnvironment);
                _environmentRepository.UnitOfWork.Commit();
            }
        }

        #endregion

        #region "Navigation methods"
        public List<MUPModel.EnvironmentApplicatif> GetAll()
        {
            return _environmentRepository.GetAll().ToList();
        }
        #endregion

        #region "private members"
        private void ValidateEnvironment(MUPModel.EnvironmentApplicatif environment)
        {
            //recover validator
            var validator = EntityValidatorFactory.CreateValidator();
            if (validator == null) return;

            if (!validator.IsValid(environment))
            {
                //TODO manage no valid environment
                throw new Exception("invalid object");
            }
        }
        #endregion

    }
}
